package cn.yuyiling.jelly.sr.service.impl;

import cn.yuyiling.jelly.qa.api.QuestionService;
import cn.yuyiling.jelly.qa.mongodb.entity.Answer;
import cn.yuyiling.jelly.qa.mongodb.entity.Question;
import cn.yuyiling.jelly.qa.mongodb.repository.QuestionRepository;
import cn.yuyiling.jelly.sr.api.RankService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;

import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

@DubboService
public class RankServiceImpl implements RankService {
    private static final String WEEKLY_ACTIVE_KEY_PREFIX = "weekly_active_score:";
    private static final DateTimeFormatter WEEK_FORMATTER = DateTimeFormatter.ofPattern("YYYYWw");

    @Autowired
    private StringRedisTemplate redisTemplate;
    @DubboReference
    private QuestionService  questionService;

    private double calculateDifficultyWeight(String difficulty) {
        return switch (difficulty) {
            case "中等" -> 2.0;
            case "困难" -> 3.0;
            default -> 1.0;
        };
    }

    @Override
    public void updateWeeklyActiveScore(Answer answer) {
        if (answer.getMetadata() == null || answer.getMetadata().getAiEvaluation() <= 0) {
            return;
        }

        String currentWeek = LocalDate.now().format(WEEK_FORMATTER);
        String redisKey = WEEKLY_ACTIVE_KEY_PREFIX + currentWeek;

        double correctRate = answer.getMetadata().getAiEvaluation() / 100.0;
        String questionId = answer.getParentId();
        Question question = questionService.getQuestionById(questionId);
        double difficultyWeight = calculateDifficultyWeight(question.getMetadata().getAiEvaluation());
        double activeScore = correctRate * difficultyWeight;
        String userId = answer.getAuthorId();
        redisTemplate.opsForZSet().incrementScore(redisKey, userId, activeScore);
        redisTemplate.expire(redisKey, Duration.ofDays(7));
    }

    @Override
    public List<String> getWeeklyTopUsers(int count) {
        String currentWeek = LocalDate.now().format(WEEK_FORMATTER);
        String redisKey = WEEKLY_ACTIVE_KEY_PREFIX + currentWeek;

        Set<ZSetOperations.TypedTuple<String>> set = redisTemplate.opsForZSet()
                .reverseRangeWithScores(redisKey, 0, count - 1);

        if (set == null) return Collections.emptyList();

        List<String> result = new ArrayList<>();
        for (ZSetOperations.TypedTuple<String> item : set) {
            result.add(item.getValue() + " (" + item.getScore().intValue() + ")");
        }
        return result;
    }

    @Override
    public void resetWeeklyRanking() {
        String lastWeek = LocalDate.now().minusWeeks(1).format(WEEK_FORMATTER);
        String redisKey = WEEKLY_ACTIVE_KEY_PREFIX + lastWeek;
        redisTemplate.delete(redisKey);
    }

}
